﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Windows;

using SnakeGame.Data;

namespace SnakeGame.Logic
{
    class Log
    {
        private bool[,] _blObstacles;

        private CollisionManager collisionManager;
        
        public Log(bool[,] LevelObstacles,  CollisionManager collManager)
        {
            _blObstacles = LevelObstacles;
            collisionManager = collManager;
        }


        #region методы управления змейкой
        public void RemoveTail(List<int[]> SnakeCoordinates)
        {
            SnakeCoordinates.RemoveAt(0);
        }

        private Key _keyLastPressed;

        public void AddSnakeHead(List<int[]> SnakeCoordinates, int[] SnakeHeadCoordinatesXY, Key keyPressed)
        {
            int[] _iAddHeadCoordinate = new int[2];

            try
            {
                switch (keyPressed)
                {
                    case Key.Up:
                        if (Key.Down != _keyLastPressed)
                        {                            
                            SnakeHeadCoordinatesXY[1] -= 1;
                            if (SnakeHeadCoordinatesXY[1] > -1)
                            {
                                _iAddHeadCoordinate[0] = SnakeHeadCoordinatesXY[0];
                                _iAddHeadCoordinate[1] = SnakeHeadCoordinatesXY[1];
                                SnakeCoordinates.Add(_iAddHeadCoordinate);
                                _keyLastPressed = Key.Up;
                            }
                            else
                            {
//!!!!!!!!!!!!!!!!!!!!!!!!!!!//змейка умерла, остановить таймер, отнять жизнь, перерисовть сначала если остались жизни
//                                collisionManager.Collision();
                                
                            }
                        }
                        else
                        {
                            goto case Key.Down;
                        }
                        break;
                    case Key.Down:
                        if (Key.Up != _keyLastPressed)
                        {;
                            SnakeHeadCoordinatesXY[1] += 1;
                            if(SnakeHeadCoordinatesXY[1] < 30)
                            {
                                _iAddHeadCoordinate[0] = SnakeHeadCoordinatesXY[0];
                                _iAddHeadCoordinate[1] = SnakeHeadCoordinatesXY[1];
                                SnakeCoordinates.Add(_iAddHeadCoordinate);
                                _keyLastPressed = Key.Down;
                            }
                            else
                            {
//!!!!!!!!!!!!!!!!!!!!!!!!!!!//змейка умерла, остановить таймер, отнять жизнь, перерисовть сначала если остались жизни
//                                collisionManager.Collision();
                            }
                        }
                        else
                        {
                            goto case Key.Up;
                        }
                        break;
                    case Key.Left:
                        if (Key.Right != _keyLastPressed)
                        {
                            SnakeHeadCoordinatesXY[0] -= 1;
                            if(SnakeHeadCoordinatesXY[0] > -1)
                            {
                                _iAddHeadCoordinate[0] = SnakeHeadCoordinatesXY[0];
                                _iAddHeadCoordinate[1] = SnakeHeadCoordinatesXY[1];
                                SnakeCoordinates.Add(_iAddHeadCoordinate);
                                _keyLastPressed = Key.Left;
                            }
                            else
                            {
//!!!!!!!!!!!!!!!!!!!!!!!!!!!//змейка умерла, остановить таймер, отнять жизнь, перерисовть сначала если остались жизни
//                                collisionManager.Collision();
                            }
                        }
                        else
                        {
                            goto case Key.Right;
                        }
                        break;
                    case Key.Right:
                        if (Key.Left != _keyLastPressed)
                        {
                            SnakeHeadCoordinatesXY[0] += 1;
                            if(SnakeHeadCoordinatesXY[0] < 30)
                            {
                                _iAddHeadCoordinate[0] = SnakeHeadCoordinatesXY[0];
                                _iAddHeadCoordinate[1] = SnakeHeadCoordinatesXY[1];
                                SnakeCoordinates.Add(_iAddHeadCoordinate);
                                _keyLastPressed = Key.Right;
                            }
                            else
                            {
//!!!!!!!!!!!!!!!!!!!!!!!!!!!//змейка умерла, остановить таймер, отнять жизнь, перерисовть сначала если остались жизни
//                                collisionManager.Collision();
                            }
                        }
                        else
                        {
                            goto case Key.Left;
                        }
                        break;
                };
            }
            catch (IndexOutOfRangeException e)
            {
                //MessageBox.Show("Змейка умерла =/");
                throw new IndexOutOfRangeException(e.Message);
            }
        }
        #endregion

        #region Методы проверки сотолкновений
        /// <summary>
        /// Проверка нахождения головы змейки и стены
        /// </summary>
        /// <param name="SnakeHeadCoordinates"> массив координат головы</param>
        public void CheckTheCollisionWithTheWall(int[] SnakeHeadCoordinates, Snake snake)
        {
            try
            {
                if (_blObstacles[SnakeHeadCoordinates[0], SnakeHeadCoordinates[1]])
                {
                    
                    snake._lives -= 1;

                    if (snake._lives > 0)
                    {
                        collisionManager.Collision("Process");
                    }
                    else
                    {
                        collisionManager.Collision("End");
                        snake._score = 0;
                    }
                }
            }
            catch (IndexOutOfRangeException e)
            {
                throw new IndexOutOfRangeException(e.Message);
            }
        }

        //Оставить ли возвращаемые значения 1 и 0 или переделать в enum !!!!!!!!!!!!!!!!!!
        /// <summary>
        /// Проверка столкновения головы змейки с едой
        /// </summary>
        /// <param name="FoodCoordinatesX">Координата x еды</param>
        /// <param name="FoodCoordinatesY">Координата y еды</param>
        /// <param name="SnakeHeadCoordinates">Массив координат головы змейки</param>
        /// <returns>1-еда съедена, 0-еда не съедена </returns>
        public int CheckTheCollisionWithTheFood(int FoodCoordinatesX, int FoodCoordinatesY, 
            int[] SnakeHeadCoordinates, Snake snake)
        {
            int _iCheckResult = 0;
            try
            {
                if (SnakeHeadCoordinates[0] == FoodCoordinatesX && SnakeHeadCoordinates[1] == FoodCoordinatesY)
                {
                    _iCheckResult = 1;
                    snake._score += 10;
                }
                else
                {
                    _iCheckResult = 0;
                }
            }
            catch (IndexOutOfRangeException e)
            {
                throw new IndexOutOfRangeException(e.Message);
            }

            return _iCheckResult;
        }

        public void CheckTheCollisionWithTheBody(List<int[]> SnakeCoordinates, int[] SnakeHeadCoordinates, Snake snake)
        {
            for(int i = 0; i < SnakeCoordinates.Count - 2; i++)
            {
                int[] cell = SnakeCoordinates[i];
                if (SnakeHeadCoordinates[0] == cell[0] && SnakeHeadCoordinates[1] == cell[1])
                {
                    snake._lives -= 1;

                    if (snake._lives > 0)
                    {
                        collisionManager.Collision("Process");
                    }
                    else
                    {
                        collisionManager.Collision("End");
                        snake._score = 0;
                    }
                }
            }
        }
        #endregion
    }
}

internal class NewCollisionEventArgs:EventArgs
{
    private readonly string gameStatus;

    public NewCollisionEventArgs(string gameStat)
    {
        gameStatus = gameStat;
    }

    public string GameStatus { get { return gameStatus; } }
}

internal class CollisionManager
{
    public event EventHandler<NewCollisionEventArgs> NewCollision;
//jkv;
    protected virtual void OnNewCollision(NewCollisionEventArgs e)
    {
        EventHandler<NewCollisionEventArgs> temp = NewCollision;

        if (temp != null)
            temp(this, e);
    }

    public void Collision(string GameStatus)
    {
        NewCollisionEventArgs e = new NewCollisionEventArgs(GameStatus);

        OnNewCollision(e);
    }
}
